package com.azxc.rapid.resource.feign;

import com.azxc.rapid.core.log.exception.ServiceException;
import com.azxc.rapid.core.oss.enums.OssStatusEnum;
import com.azxc.rapid.core.oss.model.RapidFile;
import com.azxc.rapid.core.tenant.annotation.NonDS;
import com.azxc.rapid.core.tool.api.R;
import com.azxc.rapid.core.tool.constant.RapidConstant;
import com.azxc.rapid.core.tool.utils.FileUtil;
import com.azxc.rapid.resource.builder.oss.OssBuilder;
import com.azxc.rapid.resource.entity.Attach;
import com.azxc.rapid.resource.entity.Oss;
import com.azxc.rapid.resource.service.IAttachService;
import com.azxc.rapid.resource.service.IOssService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.SneakyThrows;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import sun.misc.BASE64Decoder;

import java.io.ByteArrayInputStream;
import java.io.IOException;


@NonDS
@RestController
public class AttachClient implements IAttachClient {

	@Autowired
	private IAttachService attachService;

	@Autowired
	private OssBuilder ossBuilder;

	@Autowired
	private IOssService ossService;

	@Autowired
	private RedisTemplate redisTemplate;

	@Value(value = "${oss.replaceFlag}")
	private Boolean replaceFlag;
	@Value(value = "${oss.oldIP}")
	private String oldIP;
	@Value(value = "${oss.showIP}")
	private String showIP;


	@Override
	@PostMapping(GET_ATTACH_BY_ID)
	public R<Attach> getAttachById(Long id) {
		Attach attach = attachService.getById(id);
		return R.data(attach);
	}


	/**
	 * 	* 获取内网的资源地址,为了解决内部微服务无法访问外网的资源文件问题
	 * @param id    附件id
	 * @return    内网的地址储存地址
	 */
	@Override
	@PostMapping(GET_SOURCE_ATTACH_BY_ID)
	public R<Attach> getSourceAttachById(Long id) {
		Attach attach = attachService.getById(id);
		if(replaceFlag){
			attach.setLink(attach.getLink().replace(showIP,oldIP));
			attach.setDomain(attach.getDomain().replace(showIP,oldIP));
		}
		return R.data(attach);
	}


	@SneakyThrows
	@Override
	public R<RapidFile> putFile(MultipartFile file) {
		RapidFile rapidFile = ossBuilder.template().putFile(file.getOriginalFilename(), file.getInputStream());
		Long attachId = buildAttach(file.getSize(), rapidFile);
		rapidFile.setAttachId(attachId);
		return R.data(rapidFile);
	}

	/**
	 * 未登录用户上传base64的图片信息,base64内容太多，使用redis中的key进行传递
	 * 例如：使用定时任务发起的上传
	 *
	 * @return
	 */
	@Override
	public R<RapidFile> putBase64(String fileName, String key) {
		String base64Code = (String) redisTemplate.opsForValue().get(key);
		BASE64Decoder decoder = new BASE64Decoder();
		// 解密
		byte[] b = new byte[0];
		try {
			b = decoder.decodeBuffer(base64Code);
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 处理数据
		for (int i = 0; i < b.length; ++i) {
			if (b[i] < 0) {
				b[i] += 256;
			}
		}
		LambdaQueryWrapper<Oss> lqw = Wrappers.<Oss>query().lambda().eq(Oss::getTenantId, RapidConstant.ADMIN_TENANT_ID).eq(Oss::getStatus, OssStatusEnum.ENABLE.getNum());
		// 获取调启用的配置
		Oss o = ossService.getOne(lqw);
		if (o == null || o.getId() == null) {
			throw new ServiceException("未获取到对应的对象存储配置");
		}
		RapidFile rapidFile = ossBuilder.template(RapidConstant.ADMIN_TENANT_ID, o.getOssCode()).putFile(fileName, new ByteArrayInputStream(b));
		Long attachId = buildAttach(Long.valueOf(b.length), rapidFile);
		rapidFile.setAttachId(attachId);
		return R.data(rapidFile);
	}

	/**
	 * 未登录用户进行文件上传
	 * 例如：使用定时任务发起的上传
	 *
	 * @param file
	 * @return
	 */
	@SneakyThrows
	@Override
	public R<RapidFile> unLoginPutFile(MultipartFile file) {
		LambdaQueryWrapper<Oss> lqw = Wrappers.<Oss>query().lambda().eq(Oss::getTenantId, RapidConstant.ADMIN_TENANT_ID).eq(Oss::getStatus, OssStatusEnum.ENABLE.getNum());
		// 获取调启用的配置
		Oss o = ossService.getOne(lqw);
		if (o == null || o.getId() == null) {
			throw new ServiceException("未获取到对应的对象存储配置");
		}
		RapidFile rapidFile = ossBuilder.template(RapidConstant.ADMIN_TENANT_ID, o.getOssCode()).putFile(file.getOriginalFilename(), file.getInputStream());
		Long attachId = buildAttach(file.getSize(), rapidFile);
		rapidFile.setAttachId(attachId);
		return R.data(rapidFile);
	}

	/**
	 * 构建附件表
	 * @param fileSize  文件大小
	 * @param rapidFile 对象存储文件
	 * @return attachId
	 */
	private Long buildAttach(Long fileSize, RapidFile rapidFile) {
		String fileExtension = FileUtil.getFileExtension(rapidFile.getOriginalName());
		Attach attach = new Attach();
		if(replaceFlag){
			rapidFile.setLink(rapidFile.getLink().replace(oldIP,showIP));
			rapidFile.setDomain(rapidFile.getDomain().replace(oldIP,showIP));
		}
		attach.setLink(rapidFile.getLink());
		attach.setDomain(rapidFile.getDomain());
		attach.setName(rapidFile.getName());
		attach.setOriginalName(rapidFile.getOriginalName());
		attach.setAttachSize(fileSize);
		attach.setExtension(fileExtension);
		attachService.save(attach);
		return attach.getId();
	}


}
